suppressPackageStartupMessages({
library(Seurat)
library(tidyverse)
library(SingleCellExperiment)
library(scater)
library(pbapply)
library(future)
library(reshape2)
library(ggpubr)
library(UpSetR)
})
source("~/multiOmic_benchmark/selectFeatures.R")

Load F74 datasets (preprocessed as in makeSCElist.r). Includes raw and processed ATAC-seq and RNA-seq dataset. ATAC-seq data was reduced to gene level features as in Seurat pipeline.

f74.sce.list <- readRDS("~/my_data/integrated_thymus/F74_SCElist_20191017.RDS")
f74.atac <- f74.sce.list$ATAC
f74.rna <- f74.sce.list$RNA

Feature selection

Compare betwen HVGs from ATAC and HVGs from RNA (i.e. genes used for cell type annotation)

n_features = 4000
hvg.rna <- HVG_Seurat(f74.sce.list[["RNA"]], nfeatures = n_features) %>% {.[. %in% rownames(f74.sce.list[["ATAC"]])]}
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
hvg.atac <- HVG_Seurat(f74.atac, nfeatures = length(hvg.rna))
Calculating gene variances
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
Calculating feature variances of standardized and clipped values
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
upset(fromList(list(hvg.rna=hvg.rna, hvg.atac=hvg.atac)))

Dimensionality Reduction

f74.atac.seu <- as.Seurat(f74.atac, verbose=FALSE)
f74.atac.seu <- ScaleData(f74.atac.seu, do.center = TRUE, verbose=FALSE)
f74.atac.seu <- RunPCA(f74.atac.seu, features = hvg.rna, verbose=FALSE) 
f74.atac.seu <- RunUMAP(f74.atac.seu, reduction = "pca", dims=1:30, verbose=FALSE) 
DimPlot(f74.atac.seu, reduction = "umap", group.by = NULL) + ggtitle("scRNA-seq HVGs") 

Clustering

Accessibility of thymic markers

Provided by Cecilia

Co-accessibility of markers

Genes that are distinctive of the same clusters will tend to be co-expressed in the same cells. Hence, to test if marker genes show patterning also in accessibility, I calculate correlation of accessibility profiles of thymus development marker genes and compare co-accessibility with their correlation in gene expression.

markers <- c('PTPRC','CD4','CD8A','CD8B','CD79A','FOXN1','EPCAM','PDGFRA','GNG4',
             'FOXP3','RAG1','RAG2','PTCRA','IL7R','NKG7','CCR7')
markers <- intersect(markers, rownames(f74.atac.seu@assays$RNA@counts))
## Calculate co-accessibility of marker genes
marker.cormat.atac <- 
  f74.atac.seu@assays$RNA@scale.data[markers,] %>%
  as.matrix() %>%
  t() %>%
  cor(use="pairwise.complete.obs")
## Same on RNA
f74.rna.seu <- as.Seurat(f74.rna)
f74.rna.seu <- ScaleData(f74.rna.seu)
Centering and scaling data matrix

  |                                                                                      
  |                                                                                |   0%
  |                                                                                      
  |==                                                                              |   3%
  |                                                                                      
  |=====                                                                           |   6%
  |                                                                                      
  |=======                                                                         |   9%
  |                                                                                      
  |=========                                                                       |  12%
  |                                                                                      
  |============                                                                    |  15%
  |                                                                                      
  |==============                                                                  |  18%
  |                                                                                      
  |================                                                                |  21%
  |                                                                                      
  |===================                                                             |  24%
  |                                                                                      
  |=====================                                                           |  26%
  |                                                                                      
  |========================                                                        |  29%
  |                                                                                      
  |==========================                                                      |  32%
  |                                                                                      
  |============================                                                    |  35%
  |                                                                                      
  |===============================                                                 |  38%
  |                                                                                      
  |=================================                                               |  41%
  |                                                                                      
  |===================================                                             |  44%
  |                                                                                      
  |======================================                                          |  47%
  |                                                                                      
  |========================================                                        |  50%
  |                                                                                      
  |==========================================                                      |  53%
  |                                                                                      
  |=============================================                                   |  56%
  |                                                                                      
  |===============================================                                 |  59%
  |                                                                                      
  |=================================================                               |  62%
  |                                                                                      
  |====================================================                            |  65%
  |                                                                                      
  |======================================================                          |  68%
  |                                                                                      
  |========================================================                        |  71%
  |                                                                                      
  |===========================================================                     |  74%
  |                                                                                      
  |=============================================================                   |  76%
  |                                                                                      
  |================================================================                |  79%
  |                                                                                      
  |==================================================================              |  82%
  |                                                                                      
  |====================================================================            |  85%
  |                                                                                      
  |=======================================================================         |  88%
  |                                                                                      
  |=========================================================================       |  91%
  |                                                                                      
  |===========================================================================     |  94%
  |                                                                                      
  |==============================================================================  |  97%
  |                                                                                      
  |================================================================================| 100%
marker.cormat.rna <- 
  f74.rna.seu@assays$RNA@scale.data[markers,] %>%
  as.matrix() %>%
  t() %>%
  cor(use="pairwise.complete.obs")

We can see that the co-accessibility signal is much weaker than the co-expression signal, but these are significantly correlated.

png("~/multiOmic_benchmark/output/ATAC_EDA/ATAC_hvg_coaccessibility.png", height=500, width=500)
pheatmap::pheatmap(marker.cormat.atac, main="co-accessibility", cellwidth = 20, cellheight = 20)
dev.off()
null device 
          1 

Control w random genes

Fibroblasts markers

PDGFRA is not in the ATAC gene activity matrix (not covered enough?), so I check for genes with high co-expression with PDGFRA in RNA.

fb_markers <- c("PDGFRA")
pdgfra.x <- f74.rna.seu@assays$RNA@scale.data["PDGFRA",]
pdgfra.cor <- apply(f74.rna.seu@assays$RNA@scale.data[hvg.rna,], 1, function(x) cor(x=x, y=pdgfra.x, use="complete.obs"))
fb_markers_atac <- pdgfra.cor[which(pdgfra.cor > 0.7)]
FeaturePlot(f74.atac.seu, features = names(fb_markers_atac)) 

Compare with expression in RNA

f74.rna.seu <- ScaleData(f74.rna.seu, features = hvg.rna)
Centering and scaling data matrix

  |                                                                                                                              
  |                                                                                                                        |   0%
  |                                                                                                                              
  |========================================                                                                                |  33%
  |                                                                                                                              
  |================================================================================                                        |  67%
  |                                                                                                                              
  |========================================================================================================================| 100%
f74.rna.seu <- RunPCA(f74.rna.seu, features = hvg.rna) 
PC_ 1 
Positive:  TRBC2, LTB, CORO1A, CD1A, SMPD3, NPPC, STMN1, CHI3L2, HMGA1, LCP1 
       RGCC, LAPTM5, TRAC, IL7R, TRAV13-2, MCTP1, HIST1H1C, ITM2A, HIST1H2BJ, CD82 
       IL32, MT1X, RP3-395M20.12, SH2D2A, TRAV13-1, SMIM24, CDKN2C, TRAV8-4, PTMA, LINC01550 
Negative:  CALD1, COL5A2, COL6A1, SPARC, NFIB, TSHZ2, COL3A1, NID1, CPE, PLAC9 
       EFEMP2, MAP1B, FLRT2, FSTL1, LAMB1, COL5A1, AHNAK, MMP2, BGN, LUM 
       AKAP12, OLFML3, COL1A1, CXCL12, IGFBP4, LAMA4, MMP14, LAMC1, COL12A1, PXDN 
PC_ 2 
Positive:  LTB, OLFML3, COL5A2, MMP2, SFRP1, MXRA8, COL12A1, PLAC9, PLAT, TSHZ2 
       CALD1, CPE, NTRK2, SMOC2, TSC22D3, LUM, NID1, BOC, COL5A1, NUPR1 
       OSR1, MDFI, DKK3, COL6A1, NFIB, LAMB1, CERCAM, LAMA4, PRRX1, LRP1 
Negative:  UBE2T, TYMS, CENPM, RRM2, CENPW, ASF1B, MAD2L1, CENPU, CCNA2, CDK1 
       DTYMK, RRM1, UHRF1, DHFR, LMNB1, MKI67, CDT1, HMGB3, MND1, NUSAP1 
       ZWINT, TOP2A, KIFC1, TACC3, KIF22, CDCA5, GMNN, CENPF, NCAPG, NCAPH 
PC_ 3 
Positive:  HLA-DRA, HLA-DRB5, HLA-DRB1, TYROBP, HLA-DPA1, HLA-DQA1, CD74, HLA-DQB1, SAMHD1, C1QC 
       RNASE1, HCK, HLA-DMB, SPI1, HLA-B, STAB1, CSF1R, CD36, CTSH, FOLR2 
       TMEM176B, GIMAP4, FCER1G, IRF8, CSF2RA, CD86, PLVAP, MMP9, PLEK, HLA-DMA 
Negative:  NTRK2, SFRP1, PLAT, SCARA5, GPC3, CREB3L1, SFRP2, PTPRD, OSR1, DLK1 
       TMEFF2, OLFML3, C1QTNF2, CERCAM, GDF10, CDO1, DKK3, KAZALD1, EBF2, MXRA8 
       SMOC2, HTRA3, SGCD, THBS2, COL16A1, MMP2, CLMP, HAND2-AS1, KDELR3, COL12A1 
PC_ 4 
Positive:  APLNR, CDH5, COL4A1, COL15A1, CAV1, CRIP2, CXCL13, COL4A2, MADCAM1, KDR 
       COX4I2, CLDN5, PAPLN, MYLK, NTS, PODXL, SPNS2, RGS5, ESAM, BCAM 
       CCL17, HPN, CXorf36, CYP1B1, S100A16, SOX18, TMEM88, TIE1, KCNJ8, CCL2 
Negative:  CSF1R, PLD4, HCK, ADAP2, CD86, FOLR2, MARCH1, MRC1, SPI1, HLA-DMB 
       CD14, F13A1, SIGLEC1, TGFBI, CEBPA, LY86, IL6R, SLC15A3, CSF2RA, C3AR1 
       FCGR2A, AGR2, FGD2, BLVRB, PTAFR, SLAMF8, CXCL16, IRF5, MMP9, HRH1 
PC_ 5 
Positive:  DMTN, ANK1, RHAG, KLF1, TMOD1, TMEM56, HBZ, C17orf99, GMPR, PHOSPHO1 
       HBQ1, CR1L, HBM, TRIM58, RHCE, EPB42, SPTA1, TAL1, OSBP2, FAXDC2 
       SOX6, MYL4, SMIM1, MFSD2B, TUBB1, SELENBP1, TFR2, GFI1B, SPTB, CTSE 
Negative:  TMSB4X, PTMA, NPM1, ACTB, CORO1A, CYBA, LSP1, RPL35, ID3, CNN2 
       ARPC2, PPA1, C1QBP, RPS17, RPL22L1, SEPW1, IFITM2, STMN1, ISG15, COX5A 
       CTSC, HSPD1, PKM, LTB, GPI, HSP90AB1, ALDOA, PRMT1, CCND2, LY6E 
f74.rna.seu <- RunUMAP(f74.rna.seu, reduction = "pca", dims=1:30) 
07:46:17 UMAP embedding parameters a = 0.9922 b = 1.112
07:46:17 Read 8321 rows and found 30 numeric columns
07:46:17 Using Annoy for neighbor search, n_neighbors = 30
07:46:17 Building Annoy index with metric = cosine, n_trees = 50
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
07:46:19 Writing NN index file to temp file /tmp/RtmpAUvvXC/file52fa48b1d76e
07:46:19 Searching Annoy index using 1 thread, search_k = 3000
07:46:22 Annoy recall = 100%
07:46:22 Commencing smooth kNN distance calibration using 1 thread
07:46:24 Initializing from normalized Laplacian + noise
07:46:24 Commencing optimization for 500 epochs, with 353528 positive edges
0%   10   20   30   40   50   60   70   80   90   100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
07:46:45 Optimization finished

Add cell type annotation to RNA data

First clusters only

Output clusters & UMAP coordinates for Daniel

full_join(clusters_df, umap_df) %>%
  write_csv("~/my_data/integrated_thymus/F74_ATAC_clustersUMAP_20191021.csv")
Joining, by = "cell"
LS0tCnRpdGxlOiAiVGh5bXVzIEFUQUMtc2VxIHByZXByb2Nlc3NpbmcgYW5kIEVEQSIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CnN1cHByZXNzUGFja2FnZVN0YXJ0dXBNZXNzYWdlcyh7CmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShTaW5nbGVDZWxsRXhwZXJpbWVudCkKbGlicmFyeShzY2F0ZXIpCmxpYnJhcnkocGJhcHBseSkKbGlicmFyeShmdXR1cmUpCmxpYnJhcnkocmVzaGFwZTIpCmxpYnJhcnkoZ2dwdWJyKQpsaWJyYXJ5KFVwU2V0UikKfSkKCnNvdXJjZSgifi9tdWx0aU9taWNfYmVuY2htYXJrL3NlbGVjdEZlYXR1cmVzLlIiKQpgYGAKCkxvYWQgRjc0IGRhdGFzZXRzIChwcmVwcm9jZXNzZWQgYXMgaW4gYG1ha2VTQ0VsaXN0LnJgKS4gSW5jbHVkZXMgcmF3IGFuZCBwcm9jZXNzZWQgQVRBQy1zZXEgYW5kIFJOQS1zZXEgZGF0YXNldC4gQVRBQy1zZXEgZGF0YSB3YXMgcmVkdWNlZCB0byBnZW5lIGxldmVsIGZlYXR1cmVzIGFzIGluIFNldXJhdCBwaXBlbGluZS4gCgpgYGB7cn0KZjc0LnNjZS5saXN0IDwtIHJlYWRSRFMoIn4vbXlfZGF0YS9pbnRlZ3JhdGVkX3RoeW11cy9GNzRfU0NFbGlzdF8yMDE5MTAxNy5SRFMiKQoKZjc0LmF0YWMgPC0gZjc0LnNjZS5saXN0JEFUQUMKZjc0LnJuYSA8LSBmNzQuc2NlLmxpc3QkUk5BCmBgYAoKIyMgRmVhdHVyZSBzZWxlY3Rpb24KQ29tcGFyZSBiZXR3ZW4gSFZHcyBmcm9tIEFUQUMgYW5kIEhWR3MgZnJvbSBSTkEgKGkuZS4gZ2VuZXMgdXNlZCBmb3IgY2VsbCB0eXBlIGFubm90YXRpb24pCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpuX2ZlYXR1cmVzID0gNDAwMApodmcucm5hIDwtIEhWR19TZXVyYXQoZjc0LnNjZS5saXN0W1siUk5BIl1dLCBuZmVhdHVyZXMgPSBuX2ZlYXR1cmVzKSAlPiUgey5bLiAlaW4lIHJvd25hbWVzKGY3NC5zY2UubGlzdFtbIkFUQUMiXV0pXX0KaHZnLmF0YWMgPC0gSFZHX1NldXJhdChmNzQuYXRhYywgbmZlYXR1cmVzID0gbGVuZ3RoKGh2Zy5ybmEpKQoKdXBzZXQoZnJvbUxpc3QobGlzdChodmcucm5hPWh2Zy5ybmEsIGh2Zy5hdGFjPWh2Zy5hdGFjKSkpCmBgYAo8IS0tIENoZWNrIGdlbmUgY292ZXJhZ2UgLS0+CjwhLS0gYGBge3IsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02LCBlY2hvPUZBTFNFLCBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfSAtLT4KPCEtLSBnZW5lLmNvdmVyYWdlIDwtIE1hdHJpeDo6cm93U3Vtcyhjb3VudHMoZjc0LmF0YWMpKSAtLT4KCjwhLS0gaHZnLmF0YWMucGwgPC0gZGF0YS5mcmFtZShjb3Y9Z2VuZS5jb3ZlcmFnZSwgZ2VuZT1uYW1lcyhnZW5lLmNvdmVyYWdlKSkgJT4lIC0tPgo8IS0tICAgZHBseXI6Om11dGF0ZSh2YXI9aWZlbHNlKGdlbmUgJWluJSBodmcuYXRhYywgIkhWRy1BVEFDIiwgIk5vbi1IVkciKSkgJT4lIC0tPgo8IS0tICAgIyBtdXRhdGUodmFyPWlmZWxzZShnZW5lICVpbiUgVmFyaWFibGVGZWF0dXJlcyh0aHltdXMuYXRhYy52YXJjb3ZnZW5lcyksICJIVkciLCAiTm9uLUhWRyIpKSAlPiUgLS0+CjwhLS0gICBnZ3Bsb3QoYWVzKGZpbGw9dmFyLCBjb3YpKSArICAtLT4KPCEtLSAgIGdlb21faGlzdG9ncmFtKGJpbnM9NTApICsgLS0+CjwhLS0gICBmYWNldF93cmFwKHZhcn4uLCBzY2FsZXM9ImZyZWVfeSIsIG5yb3c9MiwgbmNvbD0xKSAtLT4KCjwhLS0gaHZnLnJuYS5wbCA8LSBkYXRhLmZyYW1lKGNvdj1nZW5lLmNvdmVyYWdlLCBnZW5lPW5hbWVzKGdlbmUuY292ZXJhZ2UpKSAlPiUgLS0+CjwhLS0gICBkcGx5cjo6bXV0YXRlKHZhcj1pZmVsc2UoZ2VuZSAlaW4lIGh2Zy5ybmEsICJIVkctUk5BIiwgIk5vbi1IVkciKSkgJT4lIC0tPgo8IS0tICAgIyBtdXRhdGUodmFyPWlmZWxzZShnZW5lICVpbiUgVmFyaWFibGVGZWF0dXJlcyh0aHltdXMuYXRhYy52YXJjb3ZnZW5lcyksICJIVkciLCAiTm9uLUhWRyIpKSAlPiUgLS0+CjwhLS0gICBnZ3Bsb3QoYWVzKGZpbGw9dmFyLCBjb3YpKSArICAtLT4KPCEtLSAgIGdlb21faGlzdG9ncmFtKGJpbnM9NTApICsgLS0+CjwhLS0gICBmYWNldF93cmFwKHZhcn4uLCBzY2FsZXM9ImZyZWVfeSIsIG5yb3c9MiwgbmNvbD0xKSAtLT4KCjwhLS0gZ2dhcnJhbmdlKGh2Zy5hdGFjLnBsLCBodmcucm5hLnBsLCBjb21tb24ubGVnZW5kID0gVFJVRSkgLS0+CjwhLS0gYGBgIC0tPgoKIyMgRGltZW5zaW9uYWxpdHkgUmVkdWN0aW9uCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpmNzQuYXRhYy5zZXUgPC0gYXMuU2V1cmF0KGY3NC5hdGFjLCB2ZXJib3NlPUZBTFNFKQpmNzQuYXRhYy5zZXUgPC0gU2NhbGVEYXRhKGY3NC5hdGFjLnNldSwgZG8uY2VudGVyID0gVFJVRSwgdmVyYm9zZT1GQUxTRSkKZjc0LmF0YWMuc2V1IDwtIFJ1blBDQShmNzQuYXRhYy5zZXUsIGZlYXR1cmVzID0gaHZnLnJuYSwgdmVyYm9zZT1GQUxTRSkgCmY3NC5hdGFjLnNldSA8LSBSdW5VTUFQKGY3NC5hdGFjLnNldSwgcmVkdWN0aW9uID0gInBjYSIsIGRpbXM9MTozMCwgdmVyYm9zZT1GQUxTRSkgCgpEaW1QbG90KGY3NC5hdGFjLnNldSwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9IE5VTEwpICsgZ2d0aXRsZSgic2NSTkEtc2VxIEhWR3MiKSAKYGBgCgo8IS0tIEFUQUMgaHZncyAtLT4KPCEtLSBgYGB7cn0gLS0+CjwhLS0gZjc0LmF0YWMuc2V1LmF0YWNodmcgPC0gYXMuU2V1cmF0KGY3NC5hdGFjKSAtLT4KPCEtLSBmNzQuYXRhYy5zZXUuYXRhY2h2ZyA8LSBTY2FsZURhdGEoZjc0LmF0YWMuc2V1LmF0YWNodmcpIC0tPgo8IS0tIGY3NC5hdGFjLnNldS5hdGFjaHZnIDwtIFJ1blBDQShmNzQuYXRhYy5zZXUuYXRhY2h2ZywgZmVhdHVyZXMgPSBodmcuYXRhYykgIC0tPgo8IS0tIGY3NC5hdGFjLnNldS5hdGFjaHZnIDwtIFJ1blVNQVAoZjc0LmF0YWMuc2V1LmF0YWNodmcsIHJlZHVjdGlvbiA9ICJwY2EiLCBkaW1zPTE6MzApICAtLT4KCjwhLS0gRGltUGxvdChmNzQuYXRhYy5zZXUuYXRhY2h2ZywgcmVkdWN0aW9uID0gInVtYXAiKSArIGdndGl0bGUoInNjQVRBQy1zZXEgSFZHcyIpICAtLT4KPCEtLSBgYGAgLS0+CgojIyBDbHVzdGVyaW5nIApgYGB7cn0KZjc0LmF0YWMuc2V1IDwtIEZpbmROZWlnaGJvcnMoZjc0LmF0YWMuc2V1LCB2ZXJib3NlID0gRikKZjc0LmF0YWMuc2V1IDwtIEZpbmRDbHVzdGVycyhmNzQuYXRhYy5zZXUsIGFsZ29yaXRobSA9IDQsIHZlcmJvc2UgPSBGKQoKRGltUGxvdChmNzQuYXRhYy5zZXUsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAnaWRlbnQnKSArIGdndGl0bGUoImxlaWRlbiIpICsKICBnZ3NhdmUoIn4vbXVsdGlPbWljX2JlbmNobWFyay9vdXRwdXQvQVRBQ19FREEvQVRBQ19odmdfY2x1c3RlcmluZy5qcGVnIiwgaGVpZ2h0ID0gNiwgd2lkdGg9OCkKYGBgCjwhLS0gbmNkIC0tPgo8IS0tIGBgYHtyfSAtLT4KPCEtLSBmNzQuYXRhYy5zZXUuYXRhY2h2ZyA8LSBGaW5kTmVpZ2hib3JzKGY3NC5hdGFjLnNldS5hdGFjaHZnKSAtLT4KPCEtLSBmNzQuYXRhYy5zZXUuYXRhY2h2ZyA8LSBGaW5kQ2x1c3RlcnMoZjc0LmF0YWMuc2V1LmF0YWNodmcsIGFsZ29yaXRobSA9IDQpIC0tPgoKPCEtLSBEaW1QbG90KGY3NC5hdGFjLnNldS5hdGFjaHZnLCByZWR1Y3Rpb24gPSAidW1hcCIpICsgZ2d0aXRsZSgibGVpZGVuIikgLS0+CjwhLS0gYGBgIC0tPgoKIyMgQWNjZXNzaWJpbGl0eSBvZiB0aHltaWMgbWFya2VycwpQcm92aWRlZCBieSBDZWNpbGlhCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9MTAsIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9CkZlYXR1cmVQbG90KGY3NC5hdGFjLnNldSwgZmVhdHVyZXMgPSBjKCdQVFBSQycsJ0NENCcsJ0NEOEEnLCdDRDhCJywnQ0Q3OUEnLCdGT1hOMScsJ0VQQ0FNJywnUERHRlJBJywnR05HNCcsICdGT1hQMycsJ1JBRzEnLCdSQUcyJywnUFRDUkEnLCdJTDdSJywnTktHNycsJ0NDUjcnKSkgKwogIGdnc2F2ZSgifi9vdXRwdXQvQVRBQ19FREEvQVRBQ19odmdfbWFya2Vycy5qcGVnIiwgaGVpZ2h0ID0gMTUsIHdpZHRoPTE1KQpgYGAKCiMjIENvLWFjY2Vzc2liaWxpdHkgb2YgbWFya2VycwoKR2VuZXMgdGhhdCBhcmUgZGlzdGluY3RpdmUgb2YgdGhlIHNhbWUgY2x1c3RlcnMgd2lsbCB0ZW5kIHRvIGJlIGNvLWV4cHJlc3NlZCBpbiB0aGUgc2FtZSBjZWxscy4gSGVuY2UsIHRvIHRlc3QgaWYgbWFya2VyIGdlbmVzIHNob3cgcGF0dGVybmluZyBhbHNvIGluIGFjY2Vzc2liaWxpdHksIEkgY2FsY3VsYXRlIGNvcnJlbGF0aW9uIG9mIGFjY2Vzc2liaWxpdHkgcHJvZmlsZXMgb2YgdGh5bXVzIGRldmVsb3BtZW50IG1hcmtlciBnZW5lcyBhbmQgY29tcGFyZSBjby1hY2Nlc3NpYmlsaXR5IHdpdGggdGhlaXIgY29ycmVsYXRpb24gaW4gZ2VuZSBleHByZXNzaW9uLiAKCmBgYHtyfQptYXJrZXJzIDwtIGMoJ1BUUFJDJywnQ0Q0JywnQ0Q4QScsJ0NEOEInLCdDRDc5QScsJ0ZPWE4xJywnRVBDQU0nLCdQREdGUkEnLCdHTkc0JywKICAgICAgICAgICAgICdGT1hQMycsJ1JBRzEnLCdSQUcyJywnUFRDUkEnLCdJTDdSJywnTktHNycsJ0NDUjcnKQptYXJrZXJzIDwtIGludGVyc2VjdChtYXJrZXJzLCByb3duYW1lcyhmNzQuYXRhYy5zZXVAYXNzYXlzJFJOQUBjb3VudHMpKQoKIyMgQ2FsY3VsYXRlIGNvLWFjY2Vzc2liaWxpdHkgb2YgbWFya2VyIGdlbmVzCm1hcmtlci5jb3JtYXQuYXRhYyA8LSAKICBmNzQuYXRhYy5zZXVAYXNzYXlzJFJOQUBzY2FsZS5kYXRhW21hcmtlcnMsXSAlPiUKICBhcy5tYXRyaXgoKSAlPiUKICB0KCkgJT4lCiAgY29yKHVzZT0icGFpcndpc2UuY29tcGxldGUub2JzIikKCiMjIFNhbWUgb24gUk5BCmY3NC5ybmEuc2V1IDwtIGFzLlNldXJhdChmNzQucm5hKQpmNzQucm5hLnNldSA8LSBTY2FsZURhdGEoZjc0LnJuYS5zZXUpCm1hcmtlci5jb3JtYXQucm5hIDwtIAogIGY3NC5ybmEuc2V1QGFzc2F5cyRSTkFAc2NhbGUuZGF0YVttYXJrZXJzLF0gJT4lCiAgYXMubWF0cml4KCkgJT4lCiAgdCgpICU+JQogIGNvcih1c2U9InBhaXJ3aXNlLmNvbXBsZXRlLm9icyIpCmBgYAoKV2UgY2FuIHNlZSB0aGF0IHRoZSBjby1hY2Nlc3NpYmlsaXR5IHNpZ25hbCBpcyBtdWNoIHdlYWtlciB0aGFuIHRoZSBjby1leHByZXNzaW9uIHNpZ25hbCwgYnV0IHRoZXNlIGFyZSBzaWduaWZpY2FudGx5IGNvcnJlbGF0ZWQuCgpgYGB7cn0KcG5nKCJ+L211bHRpT21pY19iZW5jaG1hcmsvb3V0cHV0L0FUQUNfRURBL0FUQUNfaHZnX2NvYWNjZXNzaWJpbGl0eS5wbmciLCBoZWlnaHQ9NTAwLCB3aWR0aD01MDApCnBoZWF0bWFwOjpwaGVhdG1hcChtYXJrZXIuY29ybWF0LmF0YWMsIG1haW49ImNvLWFjY2Vzc2liaWxpdHkiLCBjZWxsd2lkdGggPSAyMCwgY2VsbGhlaWdodCA9IDIwKQpkZXYub2ZmKCkKcG5nKCJ+L211bHRpT21pY19iZW5jaG1hcmsvb3V0cHV0L0FUQUNfRURBL0FUQUNfaHZnX2NvZXhwcmVzc2lvbi5wbmciLCBoZWlnaHQ9NTAwLCB3aWR0aD01MDApCnBoZWF0bWFwOjpwaGVhdG1hcChtYXJrZXIuY29ybWF0LnJuYSwgbWFpbj0iY28tZXhwcmVzc2lvbiIsIGNlbGx3aWR0aCA9IDIwLCBjZWxsaGVpZ2h0ID0gMjApCmRldi5vZmYoKQpgYGAKYGBge3IsIHdhcm5pbmc9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmxvbmcuY29ybWF0LmF0YWMgPC0gCiAgbWVsdChtYXJrZXIuY29ybWF0LmF0YWMsIHZhbHVlLm5hbWUgPSAiY29yLmFjY2Vzc2liaWxpdHkiKSAlPiUgCiAgZGlzdGluY3QoY29yLmFjY2Vzc2liaWxpdHksIC5rZWVwX2FsbCA9IFQpICU+JQogIHVuaXRlKCJwYWlyIiwgYygiVmFyMSIsICJWYXIyIikpCgpsb25nLmNvcm1hdC5ybmEgPC0gCiAgbWVsdChtYXJrZXIuY29ybWF0LnJuYSwgdmFsdWUubmFtZSA9ICJjb3IuZ2V4IikgJT4lIAogIGRpc3RpbmN0KGNvci5nZXgsIC5rZWVwX2FsbCA9IFQpICU+JQogIHVuaXRlKCJwYWlyIiwgYygiVmFyMSIsICJWYXIyIikpCgoKZnVsbF9qb2luKGxvbmcuY29ybWF0LmF0YWMsIGxvbmcuY29ybWF0LnJuYSkgJT4lCiAgZHBseXI6OmZpbHRlcihjb3IuYWNjZXNzaWJpbGl0eSE9MSkgJT4lCiAgZ2dwbG90KGFlcyhjb3IuYWNjZXNzaWJpbGl0eSwgY29yLmdleCkpICsKICBnZW9tX3BvaW50KGFscGhhPTAuNSkgKwogIGdlb21fdmxpbmUobGluZXR5cGU9MiwgeGludGVyY2VwdCA9IDApICsKICBnZW9tX2hsaW5lKGxpbmV0eXBlPTIsIHlpbnRlcmNlcHQgPSAwKSArCiAgc3RhdF9jb3IoKSArCiAgZ2d0aXRsZSgiVGh5bXVzIG1hcmtlciBnZW5lcyIpICsKICBnZ3NhdmUoIn4vbXVsdGlPbWljX2JlbmNobWFyay9vdXRwdXQvQVRBQ19FREEvQVRBQ19odmdfbWFya2Vyc0NvZXhwcmVzc2lvbi5wbmciLCBoZWlnaHQgPSA1LCB3aWR0aD01KQoKYGBgCgo8IS0tIFZpc3VhbGl6ZSBzb21lIG9mIHRoZSBzdHJvbmcgY28tYWNjZXNzaWJsZSBtYXJrZXJzIC0tPgo8IS0tIGBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NX0gLS0+CjwhLS0gcDEgPC0gRmVhdHVyZVNjYXR0ZXIoZjc0LmF0YWMuc2V1LCBmZWF0dXJlMSA9ICJSQUcxIiwgZmVhdHVyZTIgPSAiUkFHMiIsIHNsb3QgPSAic2NhbGUuZGF0YSIsIHNtb290aD1UUlVFKSAtLT4KPCEtLSBwMiA8LSBGZWF0dXJlU2NhdHRlcihmNzQucm5hLnNldSwgZmVhdHVyZTEgPSAiUkFHMSIsIGZlYXR1cmUyID0gIlJBRzIiLCBzbG90ID0gInNjYWxlLmRhdGEiLCBzbW9vdGg9VFJVRSkgLS0+Cgo8IS0tIENvbWJpbmVQbG90cyhwbG90cz1saXN0KHAxLCBwMikpIC0tPgo8IS0tIGBgYCAtLT4KCkNvbnRyb2wgdyByYW5kb20gZ2VuZXMgCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQoKcmFuZG9tIDwtIHNhbXBsZShodmcucm5hLCBzaXplID0gMTAwKQpyYW5kb20uY29ybWF0LmF0YWMgPC0gCiAgZjc0LmF0YWMuc2V1QGFzc2F5cyRSTkFAc2NhbGUuZGF0YVtyYW5kb20sXSAlPiUKICBhcy5tYXRyaXgoKSAlPiUKICB0KCkgJT4lCiAgY29yKHVzZT0icGFpcndpc2UuY29tcGxldGUub2JzIikKCiMjIFNhbWUgb24gUk5BCnJhbmRvbS5jb3JtYXQucm5hIDwtIAogIGY3NC5ybmEuc2V1QGFzc2F5cyRSTkFAc2NhbGUuZGF0YVtyYW5kb20sXSAlPiUKICBhcy5tYXRyaXgoKSAlPiUKICB0KCkgJT4lCiAgY29yKHVzZT0icGFpcndpc2UuY29tcGxldGUub2JzIikKCmxvbmcucmFuZG9tLmNvcm1hdC5hdGFjIDwtIAogIG1lbHQocmFuZG9tLmNvcm1hdC5hdGFjLCB2YWx1ZS5uYW1lID0gImNvci5hY2Nlc3NpYmlsaXR5IikgJT4lIAogIGRpc3RpbmN0KGNvci5hY2Nlc3NpYmlsaXR5LCAua2VlcF9hbGwgPSBUKSAlPiUKICB1bml0ZSgicGFpciIsIGMoIlZhcjEiLCAiVmFyMiIpKQoKbG9uZy5yYW5kb20uY29ybWF0LnJuYSA8LSAKICBtZWx0KHJhbmRvbS5jb3JtYXQucm5hLCB2YWx1ZS5uYW1lID0gImNvci5nZXgiKSAlPiUgCiAgZGlzdGluY3QoY29yLmdleCwgLmtlZXBfYWxsID0gVCkgJT4lCiAgdW5pdGUoInBhaXIiLCBjKCJWYXIxIiwgIlZhcjIiKSkKCgpmdWxsX2pvaW4obG9uZy5yYW5kb20uY29ybWF0LmF0YWMsIGxvbmcucmFuZG9tLmNvcm1hdC5ybmEpICU+JQogIGRwbHlyOjpmaWx0ZXIoY29yLmFjY2Vzc2liaWxpdHkhPTEpICU+JQogIGdncGxvdChhZXMoY29yLmFjY2Vzc2liaWxpdHksIGNvci5nZXgpKSArCiAgZ2VvbV9wb2ludChhbHBoYT0wLjUpICsKICBnZW9tX3ZsaW5lKGxpbmV0eXBlPTIsIHhpbnRlcmNlcHQgPSAwKSArCiAgZ2VvbV9obGluZShsaW5ldHlwZT0yLCB5aW50ZXJjZXB0ID0gMCkgKwogIHN0YXRfY29yKCkgKwogIGdndGl0bGUoIlJhbmRvbSBIViBnZW5lcyIpICsKICBnZ3NhdmUoIn4vb3V0cHV0L0FUQUNfRURBL0FUQUNfaHZnX3JhbmRvbUNvZXhwcmVzc2lvbi5qcGVnIiwgaGVpZ2h0ID0gOCwgd2lkdGg9OCkKCgoKYGBgCgojIyBGaWJyb2JsYXN0cyBtYXJrZXJzClBER0ZSQSBpcyBub3QgaW4gdGhlIEFUQUMgZ2VuZSBhY3Rpdml0eSBtYXRyaXggKG5vdCBjb3ZlcmVkIGVub3VnaD8pLCBzbyBJIGNoZWNrIGZvciBnZW5lcyB3aXRoIGhpZ2ggY28tZXhwcmVzc2lvbiB3aXRoIFBER0ZSQSBpbiBSTkEuCgoKYGBge3IsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTh9CmZiX21hcmtlcnMgPC0gYygiUERHRlJBIikKCnBkZ2ZyYS54IDwtIGY3NC5ybmEuc2V1QGFzc2F5cyRSTkFAc2NhbGUuZGF0YVsiUERHRlJBIixdCnBkZ2ZyYS5jb3IgPC0gYXBwbHkoZjc0LnJuYS5zZXVAYXNzYXlzJFJOQUBzY2FsZS5kYXRhW2h2Zy5ybmEsXSwgMSwgZnVuY3Rpb24oeCkgY29yKHg9eCwgeT1wZGdmcmEueCwgdXNlPSJjb21wbGV0ZS5vYnMiKSkKCmZiX21hcmtlcnNfYXRhYyA8LSBwZGdmcmEuY29yW3doaWNoKHBkZ2ZyYS5jb3IgPiAwLjcpXQoKRmVhdHVyZVBsb3QoZjc0LmF0YWMuc2V1LCBmZWF0dXJlcyA9IG5hbWVzKGZiX21hcmtlcnNfYXRhYykpIAoKYGBgCgpDb21wYXJlIHdpdGggZXhwcmVzc2lvbiBpbiBSTkEKYGBge3IsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTh9CmY3NC5ybmEuc2V1IDwtIFNjYWxlRGF0YShmNzQucm5hLnNldSwgZmVhdHVyZXMgPSBodmcucm5hKQoKZjc0LnJuYS5zZXUgPC0gUnVuUENBKGY3NC5ybmEuc2V1LCBmZWF0dXJlcyA9IGh2Zy5ybmEpIApmNzQucm5hLnNldSA8LSBSdW5VTUFQKGY3NC5ybmEuc2V1LCByZWR1Y3Rpb24gPSAicGNhIiwgZGltcz0xOjMwKSAKCkZlYXR1cmVQbG90KGY3NC5ybmEuc2V1LCBmZWF0dXJlcyA9IGMobmFtZXMoZmJfbWFya2Vyc19hdGFjKSwgIlBER0ZSQSIpKSArCiAgZ2dzYXZlKCJ+L0ZiX21hcmtlcnNfUk5BLnBkZiIsIGhlaWdodCA9IDEwLCB3aWR0aD0xMCkKYGBgCmBgYHtyLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQ9MTB9ClNldXJhdDo6VmxuUGxvdChmNzQuYXRhYy5zZXUsIGZlYXR1cmVzID0gYygiTU1QMiIsICJDT0wxMkExIiwgIlBMQVQiLCAiTlRSSzIiKSwgc2xvdCA9ICJkYXRhIiwgbmNvbCA9IDIpICAKYGBgCgojIyBBZGQgY2VsbCB0eXBlIGFubm90YXRpb24gdG8gUk5BIGRhdGEgCkZpcnN0IGNsdXN0ZXJzIG9ubHkgCmBgYHtyfQpmNzQucm5hLnNldSA8LSBGaW5kTmVpZ2hib3JzKGY3NC5ybmEuc2V1LCB2ZXJib3NlID0gRikKZjc0LnJuYS5zZXUgPC0gRmluZENsdXN0ZXJzKGY3NC5ybmEuc2V1LCBhbGdvcml0aG0gPSA0LCB2ZXJib3NlID0gRikKCkRpbVBsb3QoZjc0LnJuYS5zZXUsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAnaWRlbnQnKSArIGdndGl0bGUoImxlaWRlbiIpICsKICBnZ3NhdmUoIn4vbXVsdGlPbWljX2JlbmNobWFyay9vdXRwdXQvQVRBQ19FREEvUk5BX2h2Z19jbHVzdGVyaW5nLmpwZWciLCBoZWlnaHQgPSA2LCB3aWR0aD04KQoKYGBgCgpgYGB7cn0KYW5ub3RhdGlvbi5kZiA8LSByZWFkLmNzdigifi9teV9kYXRhL0Y3NF9STkFfb2JzLmNzdiIpCgojIGFubm90YXRpb24uZGYkWCA8LSBzdHJfcmVtb3ZlKGFubm90YXRpb24uZGYkWCwgIkY3NF8xXyIpICU+JSBzdHJfYygiXzEiKQphbm5vdGF0aW9uLmRmIDwtIGFubm90YXRpb24uZGYgJT4lCiAgbXV0YXRlKGNlbGw9c3RyX3JlbW92ZShhcy5jaGFyYWN0ZXIoWCksICJGNzRfMV8iKSAlPiUgc3RyX2MoaWZlbHNlKGJhdGNoPT0wLCdfMScsICJfMiIpKSkgCgpmNzQucm5hLnNldUBtZXRhLmRhdGEgPC0KICBmNzQucm5hLnNldUBtZXRhLmRhdGEgJT4lCiAgcm93bmFtZXNfdG9fY29sdW1uKCJjZWxsIikgJT4lCiAgbGVmdF9qb2luKGFubm90YXRpb24uZGYsIGJ5PSJjZWxsIikKCmY3NC5ybmEuc2V1QG1ldGEuZGF0YSAlPD4lCiAgY29sdW1uX3RvX3Jvd25hbWVzKCJjZWxsIikKCmdncGxvdGx5KERpbVBsb3QoZjc0LnJuYS5zZXUsIGRpbXM9MToyLCBncm91cC5ieSA9ICJhbm5vdGF0aW9uIiwgcmVkdWN0aW9uID0gInVtYXAiKSkKYGBgCgpgYGB7cn0KRmVhdHVyZVBsb3QoZjc0LnJuYS5zZXUsIGZlYXR1cmVzID0gIkhMQS1EUkEiKQpgYGAKCgojIyBPdXRwdXQgY2x1c3RlcnMgJiBVTUFQIGNvb3JkaW5hdGVzIGZvciBEYW5pZWwKYGBge3J9CmNsdXN0ZXJzX2RmIDwtIGY3NC5hdGFjLnNldUBtZXRhLmRhdGEgJT4lCiAgYXNfdGliYmxlKHJvd25hbWVzPSJjZWxsIikgJT4lCiAgc2VsZWN0KGNlbGwsIHNldXJhdF9jbHVzdGVycykKCnVtYXBfZGYgPC0gCiAgZjc0LmF0YWMuc2V1QHJlZHVjdGlvbnMkdW1hcEBjZWxsLmVtYmVkZGluZ3MgJT4lCiAgYXNfdGliYmxlKHJvd25hbWVzPSJjZWxsIikKCmZ1bGxfam9pbihjbHVzdGVyc19kZiwgdW1hcF9kZikgJT4lCiAgd3JpdGVfY3N2KCJ+L215X2RhdGEvaW50ZWdyYXRlZF90aHltdXMvRjc0X0FUQUNfY2x1c3RlcnNVTUFQXzIwMTkxMDIxLmNzdiIpCmBgYAoK